﻿using System;
using System.Collections.Generic;
using System.Text;
using static JoinBoxAlignPlug.CodeHelper;

namespace JoinBoxAlignPlug
{
    public partial class ChangTextAlignment
    {
        string[] _strs;
        Encoding Encoding;

        public ChangTextAlignment(string str1, Encoding encoding)
        {
            Encoding = encoding;
            // 处理文本数组
            _strs = str1.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
        }

        public override string ToString()
        {
            return string.Join(Environment.NewLine, _strs);
        }

        /// <summary>
        /// 修改文本对齐
        /// </summary>
        /// <param name="_strs"></param>
        public void TextAlignment(string fuhao)
        {
            // 记录重复括号的
            var repeat = new Dictionary<int, int>();

            // 记录最长的符号
            var consecutive = new List<int>();

            for (int one = 0; one < _strs.Length; one++)
            {
                if (fuhao != _annotation)
                {
                    //跳过:注释行// 预处理行#
                    if (string.IsNullOrEmpty(GetCode(_strs[one])))
                        continue;
                }

                //如果不含有符号就跳过
                var indexOne = new List<int>();
                GetFuhaoIndex(_strs[one], fuhao, indexOne);
                if (indexOne.Count == 0)
                    continue;

                int fuhaoPosition = 0;

                consecutive.Clear();

                if (fuhao == _annotation)
                {
                    // 注释符号的只需要上下行判断连续
                    IsContinuousForTwoPlus(one, ref fuhaoPosition, consecutive);
                }
                else
                {
                    // 其他符号的需要判断大括号内连续
                    IsContinuousForCurlyBraces(fuhao, one, ref fuhaoPosition, consecutive, repeat);
                }

                if (consecutive.Count < 2)
                    continue;

                //遍历括号内,在符号前面插入空格
                for (int numLine = consecutive[0]; numLine < consecutive[consecutive.Count - 1] + 1; numLine++)
                {
                    if (fuhao != _annotation)
                    {
                        //跳过:注释行// 预处理行#
                        if (string.IsNullOrEmpty(GetCode(_strs[numLine])))
                            continue;
                    }

                    // GetValidCode 注意此处[获取/设置]部分相同,所以如果修改,需要两边同步.
                    var fuhaos = new List<int>();
                    var validCode = GetValidCode(fuhao, numLine, consecutive[consecutive.Count - 1], out int jumpComment, fuhaos);
                    if (numLine == jumpComment)//没有多行注释,也就一行解决的
                    {
                        if (validCode == null)//没有有效代码部分
                            continue;
                    }

                    //跳过:不含有符号
                    if (fuhaos.Count != 0)
                    {
                        var hang = _strs[numLine];

                        var qian = hang.Substring(0, fuhaos[0]);
                        //插入几个空格,格式化会将 /*注释*/+代码 进行换行处理,所以取集合0的就好了
#if true
                        //处理中文对齐的
                        //var bys = Encoding.Default.GetByteCount(qian);
                        int bys = 0;
                        GetText2FuhaoLenth(Encoding, hang, fuhaos[0], ref bys);
#else
                        //没有处理中文的
                        var bys = fuhaos[0];
#endif
                        var chaRujige = fuhaoPosition - bys;
                        if (chaRujige > 0)
                        {
                            var hou = hang.Substring(fuhaos[0], hang.Length - fuhaos[0]);//第一个是符号
                            var sb = new StringBuilder(qian);
                            for (int cha = 0; cha < chaRujige; cha++)
                            {
                                sb.Append(" ");
                            }
                            sb.Append(hou);
                            _strs[numLine] = sb.ToString();
                        }
                    }

                    //跳过:多行注释开闭号(跳到闭号句,然后循环自增)
                    if (numLine != jumpComment)
                    {
                        numLine = jumpComment;
                        continue;
                    }
                }

                //跳过处理过=号的
                one = consecutive[consecutive.Count - 1];
            }
        }

        /// <summary>
        /// 跳过注释,跳过不含有符号
        /// </summary>
        /// <param name="fuhao">符号</param>
        /// <param name="numLine">括号上行</param>
        /// <param name="down">括号下行</param>
        /// <param name="jumpComment">段落注释多行跳到的目标行</param>
        /// <param name="fuhaos">符号所在位置的集合</param>
        /// <returns>纯注释行null,返回含有有效字符串</returns>
        List<string> GetValidCode(string fuhao, int numLine, int down, out int jumpComment, List<int> fuhaos)
        {
            var hang = _strs[numLine];

            //跳过:多行注释开闭号,跳过区间,第一行可能有代码,所以到最后才处理  开号/* 闭号*/
            jumpComment = JumpComments(numLine, down);

            //跳过:单行注释开闭号  开号/* 闭号*/     例如这样的 /*a"=a"a*/
            var codes = GetCommentCodes(hang);
            if (codes.Count != 0)//没有代码部分的纯注释行
            {
                foreach (var code in codes)//遍历被切割的代码部分
                {
                    GetFuhaoIndex(code, fuhao, fuhaos);
                }

                // 符号长度等于1时,将判断两边是空格,才能不影响其他连续的符号,例如+= -= =>
                if (fuhao.Length == 1)
                {
                    foreach (var pt in fuhaos.ToArray())
                    {
                        if (pt + 1 < _strs[numLine].Length - 1 &&
                            pt - 1 > -1 &&
                            hang[pt + 1] == ' ' &&
                            hang[pt - 1] == ' ')
                        {
                            break;
                        }
                        fuhaos.RemoveAt(0);
                    }
                }
                return codes;//证明是有效代码行,不是单行多行注释行
            }
            return null;
        }

        /// <summary>
        /// 末尾删除空格
        /// </summary>
        public void TextTrimEnd()
        {
            //这里每行都处理,所以用两个循环,以免跳过
            for (int i = 0; i < _strs.Length; i++)
                _strs[i] = _strs[i].TrimEnd();
        }
    }
}
